<?php
namespace App\Services;

use Clue\React\Redis\Client as RedisClient;
use Clue\React\Redis\Factory as RedisFactory;
use React\Promise\PromiseInterface;
use React\EventLoop\Loop;
class RedisSocketService
{
    private static ?RedisClient $clientInstance = null; // 存储解析后的客户端实例
    private static ?PromiseInterface $connectionPromise = null; // 存储连接Promise

    public static function closeConnection() : Bool
    {
        if (self::$clientInstance === null) {
            return true;
        }

        return self::$clientInstance->quit()->then(function () {
            self::$clientInstance = null;
            self::$connectionPromise = null;
            return true;
        });
    }

    private static function getClient() : PromiseInterface
    {
        if (self::$clientInstance !== null) {
            return resolve(self::$clientInstance);
        }

        $factory = new RedisFactory(Loop::get());

        $uri = sprintf(
            '%s:%d?password=%s',
            config('database.redis.default.host'),
            config('database.redis.default.port'),
            config('database.redis.default.password')
        );

        self::$connectionPromise = $factory
            -> createClient($uri)
            -> then(function (RedisClient $client) {
                self::$clientInstance = $client;
                return $client;
            });

        return self::$connectionPromise;
    }

    public static function publishMessage($data): PromiseInterface
    {
        return self::getClient()->then(
            function (RedisClient $client) use ($data) {
                return $client
                    ->publish('websocket_send_channel', json_encode($data))
                    ->then(
                        function ($count) use ($data) {
                            RedisSocketService::closeConnection();

                            return $count;
                        },
                        function (\Exception $e) {
                            throw new \Exception("发布失败: " . $e->getMessage());
                        }
                    );
            }
        );
    }
    public static function subscribeMessage(array $args) : PromiseInterface
    {
        $data = [
            'op' => 'subscribe',
            'args' => $args
        ];

        return self::publishMessage($data);
    }

    public static function unSubscribeMessage(array $args) : PromiseInterface
    {
        $data = [
            'op' => 'unsubscribe',
            'args' => $args
        ];

        return self::publishMessage($data);
    }
}
